/*
 * TestFlota.cpp
 *
 *  Created on: 14/02/2010
 *      Author: San Martín, Matías I.
 */

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdio>
#include <errno.h>


#include "../../Aplicacion/Modelo/Common/Flota.h"
#include "../../Framework/Excepciones/BaseExcepcion.h"

using namespace std;

using namespace aplicacion;

static Posicion partida(50,50);
static Posicion destino(500,50);

static Flota* crearFlota()
{
	IdFlota id(1);
	IdJuego idJuego(1000);
	IdJugador idDuenio(50,idJuego);
	id.setIdJugador(idDuenio);

	return new Flota(id, 100 /*cant naves*/, 1 /*semilla*/,
				50 /*escala distr*/,
				partida, destino,
				5 /*tiempo*/);
}

static void imprimirFlota(const Flota& flota)
{
	t_constPtrNaves* naves = flota.getNavesPorTiempoHastaCantidad(flota.getCantidadNaves());

	t_constPtrNaves::iterator fin = naves->end();
	for (t_constPtrNaves::iterator i = naves->begin(); i != fin; i++)
	{
		cout << *(*i) << " Tiempo arribo " << (*i)->getTiempoArribo(destino) << "\n";
	}

	delete naves;

}

/**
 * Este test esta acoplado a los valores de la creacion
 */
static void verificarPorTiempo(const Flota& flota)
{
	bool ok = true;
	t_constPtrNaves* naves = flota.getNavesPorTiempoHasta(45 + 5);
	if (naves->size() != 67)
	{
		cerr << "TIEMPO: cantidad de naves incorrecta: se esperaban 67 se obtuvieron "
				<< naves->size() << "\n";
		ok = false;
	}

	t_constPtrNaves::iterator ultima = --naves->end();
	if (ok && (*ultima)->getTiempoArribo(destino) != 45)
	{
		cerr << "TIEMPO: tiempo de arribo de nave incorrecto: se esperaba 45 se obtuvo "
				<< (*ultima)->getTiempoArribo(destino) << "\n";
		ok = false;
	}

	delete naves;
	if (ok)
		cout << "Por tiempo de arribo OK\n";

}

/**
 * Este test esta acoplado a los valores de la creacion
 */
static void verificarPorCantidad(const Flota& flota)
{
	t_constPtrNaves* naves = flota.getNavesPorTiempoHastaCantidad(60);
	bool ok = true;
	if (naves->size() != 60)
	{
		cerr << "CANT: cantidad de naves incorrecta: se esperaban 60 se obtuvieron "
				<< naves->size() << "\n";
		ok = false;
	}

	t_constPtrNaves::iterator ultima = --naves->end();
	if (ok && (*ultima)->getTiempoArribo(destino) != 45)
	{
		cerr << "CANT: tiempo de arribo de nave incorrecto: se esperaba 45 se obtuvo "
				<< (*ultima)->getTiempoArribo(destino) << "\n";
		ok = false;
	}

	delete naves;
	if (ok)
		cout << "Por cantidad OK\n";

}

/**
 * Este test esta acoplado a los valores de la creacion
 */
static void verificarActualizacion(Flota& flota)
{
	const T_TIEMPO tiempoFinal = 45 + 5; //5 es el tiempo inicial indicado en la flota
	bool ok = true;
	size_t cantArribaran = flota.arribaran(tiempoFinal);
	if (cantArribaran != 67)
	{
		cerr << "ACT: cantidad de naves incorrecta: se esperaban 67 se obtuvieron "
				<< cantArribaran << "\n";
		ok = false;
	}else {
		size_t arribaron = flota.setTiempo(tiempoFinal);
		if (arribaron != cantArribaran)
		{
			cerr << "ACT: cantidad de naves que arribaron incorrecta: se "
					"esperaban " << cantArribaran << " se obtuvieron "
							<< arribaron << "\n";
					ok = false;
		}else{
			if (flota.getCantidadNaves() != 33)
			{
				cerr << "ACT: cantidad de naves que restan incorrecta, "
						"esperaban 33 y se obtuvieron " << flota.getCantidadNaves()
						<< "\n";
				ok = false;
			}
		}
	}
	if (ok)
		cout << "Actualizar OK\n";

}

static void verificarGuardado(const Flota& flota)
{
	const char* pathname = "datos.tmp";
	try{

		int fd = open(pathname, O_RDWR|O_CREAT|O_TRUNC,0777);

		if (fd == -1)
		{
			cerr << "GUARD: No se pudo abrir el archivo: " << strerror(errno) << endl;
		} else 	{
			flota.save(fd);

			Flota cargada;

			if (lseek(fd,0,SEEK_SET) == -1) return;
			cargada.load(fd);

			bool ok = true;
			if (flota.getCantidadNaves() != cargada.getCantidadNaves())
			{
				cerr << "GUARD: La cantdiad de naves de la flota cargada no coincide"
						" con las guardadas, las guardadas fueron " << flota.getCantidadNaves()
						<< " y las cargadas " << cargada.getCantidadNaves() << "\n";
				ok = false;
			}else{
				//comparo que las naves sean las mismas
				t_constPtrNaves* naves = flota.getNavesPorTiempoHastaCantidad(flota.getCantidadNaves());
				t_constPtrNaves* navesCargada = cargada.getNavesPorTiempoHastaCantidad(cargada.getCantidadNaves());

				size_t pos = 0;
				t_constPtrNaves::iterator fin = naves->end();
				t_constPtrNaves::iterator iC = navesCargada->begin();
				for (t_constPtrNaves::iterator i = naves->begin(); ok && i != fin; i++,iC++, pos++)
				{
					if (**i != **iC)
					{
						cerr << "GUARD: Las naves " << pos << " no coinciden: "<< "\n"
								<< "la guardada " <<  **i << " es distinta a la cargada"
								<< **iC << "\n";
						ok = false;
					}
				}

				delete navesCargada;
				delete naves;
			}

			close(fd);

			if (ok)
				cout << "Guardado OK\n";
		}
	}catch (BaseExcepcion* e)
	{
		cerr << "Excepcion: " << e->what() << endl;
		delete e;
	}

	remove ( pathname );
}

int main(int argc, char **argv) {

	Flota* flota = crearFlota();

	imprimirFlota(*flota);

	verificarPorTiempo(*flota);

	verificarPorCantidad(*flota);

	verificarGuardado(*flota);

	verificarActualizacion(*flota);

	delete flota;
}



